//Simple Portable Greymap image editor
//21/03/2012
//HSXSHU003

#include <iostream>
#include <fstream>
#include "greymap.h"
#include <string>
#include "cmdline_parser.h"

using namespace std;


hsxshu003::PGM_editor::PGM_editor () //default constructor
{

 width = 0;
 height = 0;
 pgm_buffer = NULL;
  
}

hsxshu003::PGM_editor::PGM_editor (const PGM_editor& source) //copy constructor
{
  
	width = source.width;
	height = source.height;

	pgm_buffer = new pixel [width*height];

	for (int x = 0; x < width*height; x++)
	 pgm_buffer[x] = source.pgm_buffer[x];

}

hsxshu003::PGM_editor::~PGM_editor() //destructor
{
  
	if (pgm_buffer != NULL)
	{
	 delete[]  pgm_buffer;
	 pgm_buffer = NULL;
  }

}

void hsxshu003::PGM_editor::invert () //invert the rgb values of all pixels in buffer
{
  
	for (int x = 0; x < width*height ; x++)   
	 pgm_buffer[x] = 255 - pgm_buffer[x];

}

void hsxshu003::PGM_editor::darken (int amount) //darken image
 {
  
	 int min, max;

	 min = max = pgm_buffer[0];

	 for (int x = 1; x < width*height; x++) //find min and max pixels
	 {
    if (pgm_buffer[x] > max)
		 max = pgm_buffer[x];
		if (pgm_buffer[x] < min)
		 min = pgm_buffer[x];

	 }

   for (int x = 0; x < width*height; x++)
   {

		int temp_i = pgm_buffer[x]; //for calculating pixel value with integers to prevent truncation problems

	  pgm_buffer[x] = pixel((amount * (temp_i - min) ) / ( max - min ));
   
	 }

}

void hsxshu003::PGM_editor::lighten (int amount) //lighten image
{
   int min, max;

	 min = max = pgm_buffer[0];

	 for (int x = 1; x < width*height; x++) //find min and max pixels
	 {
    if (pgm_buffer[x] > max)
		 max = pgm_buffer[x];
		if (pgm_buffer[x] < min)
		 min = pgm_buffer[x];
	 }

	 for (int x = 0; x < width*height; x++)
	 {
	  int temp_i = pgm_buffer[x];

	  pgm_buffer[x] = (255 - amount + ( amount * ( temp_i - min ) ) / ( max - min ));
   }

}

hsxshu003::PGM_editor& hsxshu003::PGM_editor::operator= (const hsxshu003::PGM_editor& source) //overload assignment operator to deep copy
{

  if (this != &source) //check for self-assignment 
  {
   width = source.width; //copy over variables
	 height = source.height;

	 pgm_buffer = new pixel[width*height];

   for (int x = 0; x < width*height; x++)
    pgm_buffer[x] = source.pgm_buffer[x];

	}
	
  return *this;

}

inline hsxshu003::pixel& hsxshu003::PGM_editor::operator() (const int w, const int h) //returns reference to pixel at specified location
{
 
 return pgm_buffer[h*width + w];

}


hsxshu003::PGM_editor::iterator hsxshu003::PGM_editor::begin () //returns iterator at beginning of image
{
 
 return iterator(*this,0,0); 

}

hsxshu003::PGM_editor::iterator hsxshu003::PGM_editor::end () //returns iterator at end of image
{

 return iterator(*this,width, height);

}

int main (int argc, char * argv[])
{

 cmdline_parser options;
 string filename;

 

 if(!options.process_cmdline(argc, argv)) //if error processing command line, print appropriate error stuff
 {
  options.print_errors(cerr);
  options.print_help(cout);
  return 1;
 }

 if(options.should_print_help())
 {
  options.print_help(cout);
  return 0;
 }

 filename = options.get_input_filename();
 
 hsxshu003::PGM_editor photoshop;

 ifstream reader;
 reader.open(filename.c_str());

 reader >> photoshop;

 reader.close();

 if(options.should_darken())
 {
    string ofilename = options.get_darken_filename();
    
    hsxshu003::PGM_editor darkened = photoshop;

    darkened.darken(options.get_darken_amount());
    
    ofstream writer;
    writer.open(ofilename.c_str());

    writer << darkened;
    
    writer.close();       
 }

 if(options.should_lighten())
 {
    string ofilename = options.get_lighten_filename();
    
    hsxshu003::PGM_editor lightened = photoshop;

    lightened.lighten(options.get_lighten_amount());
    
    ofstream writer;
    writer.open(ofilename.c_str());

    writer << lightened;
    
    writer.close();
 }

 if(options.should_invert())
 {
    string ofilename = options.get_invert_filename();
    
    hsxshu003::PGM_editor inverted = photoshop;

    inverted.invert();
    
    ofstream writer;
    writer.open(ofilename.c_str());

    writer << inverted;
    
    writer.close();       
 }


 



}
